﻿using System;
using System.Diagnostics;
using StillDesign;
using SlimDX;

namespace Editor
{
    internal class PhysicsUtils
    {
        private class PhysXOutput : StillDesign.PhysX.UserOutputStream
        {
            public override void Print(string message)
            {
                Debug.WriteLine(message, "PhysX");
            }

            public override StillDesign.PhysX.AssertResponse ReportAssertionViolation(string message, string file, int lineNumber)
            {
                Debug.WriteLine(message + "\n\t" + file + " : " + lineNumber, "PhysX");
                return StillDesign.PhysX.AssertResponse.Breakpoint;
            }

            public override void ReportError(StillDesign.PhysX.ErrorCode errorCode, string message, string file, int lineNumber)
            {
                Debug.WriteLine("ERROR " + errorCode.ToString() + "\n\t" + message + "\n\t\t" + file + " : " + lineNumber, "PhysX");
            }
        }

        private static PhysXOutput m_PhysXOutput;
        private static StillDesign.PhysX.Core m_PhysXCore;
        private static StillDesign.PhysX.Scene m_PhysXScene;

        public static StillDesign.PhysX.Core PhysXCore
        {
            get { return m_PhysXCore; }
        }

        public static StillDesign.PhysX.Scene PhysXScene
        {
            get { return PhysicsUtils.m_PhysXScene; }
            set { PhysicsUtils.m_PhysXScene = value; }
        }

        public static bool CreatePhysX()
        {
            if (m_PhysXCore != null)
                return true;

            try
            {
                StillDesign.PhysX.CoreDescription description = new StillDesign.PhysX.CoreDescription();
                m_PhysXOutput = new PhysXOutput();
                m_PhysXCore = new StillDesign.PhysX.Core(description, m_PhysXOutput);

                StillDesign.PhysX.SceneDescription sceneDescription = new StillDesign.PhysX.SceneDescription();
                sceneDescription.Name = "Scene";
                sceneDescription.Gravity = new SlimDX.Vector3(0.0f, 0.0f, 0.0f);//-9.81f);
                sceneDescription.GroundPlaneEnabled = false;
                sceneDescription.MaximumTimestep = 1.0f / 60.0f;
                sceneDescription.MaximumIterations = 8;
                sceneDescription.TimestepMethod = StillDesign.PhysX.TimestepMethod.Fixed;
                sceneDescription.SimulationType = StillDesign.PhysX.SimulationType.Hardware;
                sceneDescription.Flags = StillDesign.PhysX.SceneFlag.EnableMultithread;
                sceneDescription.InternalThreadCount = 2;
                sceneDescription.BackgroundThreadCount = 2;
                sceneDescription.UpAxis = Properties.Settings.Default.ZAxisUp ? 2 : 1;

                m_PhysXScene = m_PhysXCore.CreateScene(sceneDescription);

                // Connect to the remote debugger if its there
                m_PhysXCore.Foundation.RemoteDebugger.Connect("localhost");
            }
            catch (DllNotFoundException ex)
            {
                m_PhysXScene = null;
                m_PhysXCore = null;
                m_PhysXOutput = null;
                Debug.Fail(ex.Message, ex.ToString());
                return false;
            }

            return true;
        }
    }
}
